package com.okex.demo.task;

import com.okex.demo.config.WebSocketEventListener;
import com.okex.demo.model.Account;
import com.okex.demo.model.TickerInfo;
import com.okex.demo.service.AccountService;
import com.okex.demo.service.OkexApiService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;

/**
 * 行情数据定时任务
 * 
 * 注意：此类已弃用，改为使用DataPollingService按需执行
 * 所有@Scheduled注解已取消，避免重复执行轮询任务
 */
@Slf4j
@Component
@Deprecated
public class MarketDataTask {

    @Autowired
    private OkexApiService okexApiService;

    @Autowired
    private AccountService accountService;

    @Autowired
    private SimpMessagingTemplate messagingTemplate;
    
    @Autowired
    private WebSocketEventListener webSocketEventListener;

    @Value("${okex.default.inst-id:BTC-USDT}")
    private String defaultInstId;

    // 用于记录最近一次推送的市场类型
    private String lastPushedInstType = "SWAP";

    /**
     * 定时获取SWAP永续合约行情数据并推送
     * 已弃用，改为使用DataPollingService按需执行
     */
    // @Scheduled(fixedDelay = 15000) - 已取消调度
    @Deprecated
    public void fetchSwapMarketsAndPush() {
        // 注释：该方法已不再自动调度
        // 如果没有活跃连接，跳过执行
        if (!webSocketEventListener.hasActiveConnections()) {
            log.debug("没有活跃WebSocket连接，跳过SWAP行情数据获取任务");
            return;
        }
        
        try {
            log.debug("开始获取SWAP永续合约行情数据...");
            // 获取SWAP永续合约行情
            List<TickerInfo> tickers = okexApiService.getTickersList("SWAP", null, null);

            // 确保数据有类型标记
            for (TickerInfo ticker : tickers) {
                if (ticker.getInstType() == null || ticker.getInstType().isEmpty()) {
                    ticker.setInstType("SWAP");
                }
            }

            if (!tickers.isEmpty()) {
                // 保存推送类型
                lastPushedInstType = "SWAP";

            // 将数据推送到WebSocket主题
            messagingTemplate.convertAndSend("/topic/all-markets", tickers);
                log.debug("已推送SWAP行情数据: {} 条", tickers.size());
            } else {
                log.warn("获取到空的SWAP行情数据");
            }
        } catch (Exception e) {
            log.error("获取或推送SWAP行情数据失败: {}", e.getMessage(), e);
        }
    }

    /**
     * 定时获取SPOT现货行情数据并推送
     * 已弃用，改为使用DataPollingService按需执行
     */
    // @Scheduled(fixedDelay = 1000) - 已取消调度
    @Deprecated
    public void fetchSpotMarketsAndPush() {
        // 注释：该方法已不再自动调度
        // 如果没有活跃连接，跳过执行
        if (!webSocketEventListener.hasActiveConnections()) {
            log.debug("没有活跃WebSocket连接，跳过SPOT行情数据获取任务");
            return;
        }
        
        try {
            log.debug("开始获取SPOT现货行情数据...");
            // 获取SPOT现货行情
            List<TickerInfo> tickers = okexApiService.getTickersList("SPOT", null, null);

            // 确保数据有类型标记
            for (TickerInfo ticker : tickers) {
                if (ticker.getInstType() == null || ticker.getInstType().isEmpty()) {
                    ticker.setInstType("SPOT");
                }
            }

            if (!tickers.isEmpty()) {
                // 将数据推送到WebSocket主题
                messagingTemplate.convertAndSend("/topic/spot-markets", tickers);
                log.debug("已推送SPOT行情数据: {} 条", tickers.size());
            } else {
                log.warn("获取到空的SPOT行情数据");
            }
        } catch (Exception e) {
            log.error("获取或推送SPOT行情数据失败: {}", e.getMessage(), e);
        }
    }

    /**
     * 定时获取账户关联的产品行情并推送
     * 已弃用，改为使用DataPollingService按需执行
     */
    // @Scheduled(fixedDelay = 2000) - 已取消调度
    @Deprecated
    public void fetchAccountTickersAndPush() {
        // 注释：该方法已不再自动调度
        // 如果没有活跃连接，跳过执行
        if (!webSocketEventListener.hasActiveConnections()) {
            log.debug("没有活跃WebSocket连接，跳过产品行情数据获取任务");
            return;
        }
        
        try {
            // 获取所有订阅的产品ID
            Set<String> subscribedProducts = StreamSupport
                .stream(webSocketEventListener.getSubscribedProducts().spliterator(), false)
                .collect(Collectors.toSet());
            
            // 如果没有订阅的产品，至少获取默认产品的行情
            if (subscribedProducts.isEmpty()) {
                log.debug("没有订阅的产品，只获取默认产品: {}", defaultInstId);
                subscribedProducts.add(defaultInstId);
            }
            
            // 获取活跃账户列表
            List<Account> activeAccounts = accountService.findAllActive();
            Set<String> knownProductIds = new HashSet<>();
            
            // 如果有活跃账户，将产品ID添加到已知产品列表
            if (activeAccounts != null && !activeAccounts.isEmpty()) {
                activeAccounts.stream()
                    .map(acc -> acc.getInstId())
                    .filter(instId -> instId != null && !instId.isEmpty())
                    .forEach(knownProductIds::add);
            }
            
            // 合并已知产品和订阅产品列表，以确保已知的产品也会被查询
            List<String> instIdsToQuery = new ArrayList<>(subscribedProducts);
            if (!subscribedProducts.contains(defaultInstId)) {
                instIdsToQuery.add(defaultInstId); // 确保默认产品总是被查询
            }
            
            // 如果需要查询的产品列表为空，跳过
            if (instIdsToQuery.isEmpty()) {
                log.debug("没有需要查询的产品");
                return;
            }
            
            log.info("定时任务: 准备获取 {} 个产品的行情数据: {}", instIdsToQuery.size(), instIdsToQuery);
            Map<String, TickerInfo> tickerMap = new HashMap<>();
            int successCount = 0;

            // 获取每个产品的行情，只查询有订阅的产品
            for (String instId : instIdsToQuery) {
                try {
                    // 只有订阅了该产品或者是默认产品才查询
                    if (subscribedProducts.contains(instId) || instId.equals(defaultInstId)) {
                        TickerInfo ticker = okexApiService.getTicker(instId);
                        if (ticker != null) {
                            // 设置最新更新时间
                            Date now = new Date();
                            ticker.setUpdateTime(now);
    
                            tickerMap.put(instId, ticker);
                            successCount++;
    
                            // 推送到个别产品的主题
                            if (webSocketEventListener.hasProductSubscriptions(instId)) {
                                log.info("定时任务: 推送 {} 产品数据到 /topic/ticker/{}", instId, instId);
                                messagingTemplate.convertAndSend("/topic/ticker/" + instId, ticker);
                            }
                        }
                    }
                } catch (Exception e) {
                    log.warn("获取产品 {} 行情数据失败: {}", instId, e.getMessage());
                }
            }

            if (successCount > 0) {
                log.info("定时任务: 成功获取并推送 {} 个产品的行情数据", successCount);
            } else {
                log.warn("所有产品行情数据获取失败");
                pushDefaultTicker();
                return;
            }

            // 将默认产品的行情推送到通用主题
            if (tickerMap.containsKey(defaultInstId)) {
                messagingTemplate.convertAndSend("/topic/ticker", tickerMap.get(defaultInstId));
                log.info("定时任务: 已推送默认产品 {} 行情数据到主题 /topic/ticker", defaultInstId);
            } else if (!tickerMap.isEmpty()) {
                // 如果没有默认产品，但有其他产品，推送第一个产品的行情
                String firstInstId = instIdsToQuery.get(0);
                if (tickerMap.containsKey(firstInstId)) {
                    messagingTemplate.convertAndSend("/topic/ticker", tickerMap.get(firstInstId));
                    log.info("定时任务: 已推送首个产品 {} 行情数据到主题 /topic/ticker", firstInstId);
                }
            }
        } catch (Exception e) {
            log.error("定时任务: 获取并推送账户产品行情数据失败: {}", e.getMessage(), e);
            // 尝试推送默认产品行情作为备选
            pushDefaultTicker();
        }
    }

    /**
     * 推送默认产品行情的辅助方法
     * 已弃用，改为使用DataPollingService
     */
    @Deprecated
    private void pushDefaultTicker() {
        try {
            TickerInfo defaultTicker = okexApiService.getTicker(defaultInstId);
            if (defaultTicker != null) {
                messagingTemplate.convertAndSend("/topic/ticker", defaultTicker);
                log.debug("已推送默认产品行情数据: {}", defaultInstId);
            } else {
                log.warn("无法获取默认产品 {} 行情数据", defaultInstId);
            }
        } catch (Exception e) {
            log.error("获取默认产品 {} 行情数据失败: {}", defaultInstId, e.getMessage());
        }
    }

    /**
     * 按需推送最新行情数据
     * 已弃用，改为使用DataPollingService按需执行
     */
    // @Scheduled(fixedRate = 5000) - 已取消调度
    @Deprecated
    public void pushLatestTickerData() {
        // 注释：该方法已不再自动调度
        // 如果没有活跃连接，跳过执行
        if (!webSocketEventListener.hasActiveConnections()) {
            log.debug("没有活跃WebSocket连接，跳过数据推送任务");
            return;
        }
        
        try {
            // 获取所有订阅的产品ID
            Set<String> subscribedProducts = StreamSupport
                .stream(webSocketEventListener.getSubscribedProducts().spliterator(), false)
                .collect(Collectors.toSet());
            
            // 如果没有订阅的产品，跳过执行
            if (subscribedProducts.isEmpty()) {
                log.debug("没有订阅的产品，跳过数据推送");
                return;
            }
            
            log.info("定时推送: 有 {} 个订阅的产品", subscribedProducts.size());
            
            // 只查询和推送有订阅者的产品
            for (String instId : subscribedProducts) {
                // 获取最新行情
                TickerInfo ticker = okexApiService.getTicker(instId);
                if (ticker != null) {
                    // 设置更新时间
                    ticker.setUpdateTime(new Date());
                    log.info("定时推送产品行情: {}", instId);
                    
                    // 推送到WebSocket
                    messagingTemplate.convertAndSend("/topic/ticker/" + instId, ticker);
                }
            }
        } catch (Exception e) {
            log.error("定时推送行情数据异常: {}", e.getMessage(), e);
        }
    }
}

